package com.hang.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hang.entity.Department;
import com.hang.entity.User;
import com.hang.exception.MyException;
import com.hang.exception.MyExceptionEnum;
import com.hang.mapper.UserMapper;
import com.hang.mapstruct.DepartmentMapStruct;
import com.hang.mapstruct.UserMapStruct;
import com.hang.model.dto.request.DepartmentModelReq;
import com.hang.model.dto.request.DepartmentQueryModelReq;
import com.hang.model.dto.request.DepartmentUserDTO;
import com.hang.model.dto.request.DepartmentUserQueryDTO;
import com.hang.model.dto.response.DepartmentQueryListVO;
import com.hang.model.vo.UserInfoVO;
import com.hang.service.IDepartmentService;
import com.hang.mapper.DepartmentMapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 */
@Service
@AllArgsConstructor
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department>
    implements IDepartmentService{

    private DepartmentMapper departmentMapper;

    private DepartmentMapStruct departmentMapStruct;

    private UserMapper userMapper;

    private UserMapStruct userMapStruct;

    /**
     * 创建部门
     * @param departmentModelReq
     * @return
     */
    @Override
    public boolean createDepartment(DepartmentModelReq departmentModelReq) {
        if(ObjectUtils.isEmpty(departmentModelReq)){
            throw new MyException(MyExceptionEnum.OBJECT_IS_NULL);
        }

        Department department = departmentMapStruct.departmentModelReqToDepartment(departmentModelReq);

        //查看部门号有没有被使用
        checkDeptNoUsed(departmentModelReq);

        if(!ObjectUtils.isEmpty(department)){
            departmentMapper.insert(department);
            return true;
        }

        return false;
    }

    /**
     * 修改部门
     *      先搜索修改部门
     *      查看部门名是否修改，如果修改需要修改用户表所对应的
     * @param departmentModelReq
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDepartment(DepartmentModelReq departmentModelReq) {
        Long deptId = departmentModelReq.getDeptId();

        if(ObjectUtils.isEmpty(deptId)){
            throw new MyException(MyExceptionEnum.ID_IS_NULL);
        }

        Department dbDepartment = departmentMapper.selectById(deptId);

        //查看部门号有没有被使用
        checkUpdateDeptNoUsed(dbDepartment.getDeptNo(),departmentModelReq);

        String oldDepartmentName = dbDepartment.getDeptName();

        dbDepartment = departmentMapStruct.departmentModelReqToDepartment(departmentModelReq);
        String newDepartmentName = departmentModelReq.getDeptName();

        //更新操作
        dbDepartment.setDeptId(deptId);
        int updateDeptFlag = departmentMapper.updateById(dbDepartment);

        //关联操作
        if(!StrUtil.equals(oldDepartmentName,newDepartmentName)){
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.lambda().eq(User::getDeptName,oldDepartmentName);

            List<User> users = userMapper.selectList(userQueryWrapper);
            users.forEach(user -> {
                user.setDeptName(newDepartmentName);
                userMapper.updateById(user);
            });
        }

        return updateDeptFlag > 0?Boolean.TRUE:Boolean.FALSE;
    }

    /**
     * 按条件搜索部门列表
     *      若搜索框为空且查找所有类型的部门，则进行全量搜索
     *
     *      否则按照逻辑与进行搜索条件和指定类型的部门进行搜索
     *
     * @param departmentQueryModelReq
     * @return
     */
    @Override
    public DepartmentQueryListVO getDepartmentsByCondition(DepartmentQueryModelReq departmentQueryModelReq) {
        if(ObjectUtils.isEmpty(departmentQueryModelReq)){
            throw new MyException(MyExceptionEnum.OBJECT_IS_NULL);
        }

        Integer pageNum = departmentQueryModelReq.getPageNum();
        Integer pageSize = departmentQueryModelReq.getPageSize();

        String condition = departmentQueryModelReq.getCondition();

        Page<Department> pages = new Page<>(pageNum,pageSize);
        QueryWrapper<Department> departmentQueryWrapper = new QueryWrapper<>();

        DepartmentQueryListVO departmentQueryListVO = new DepartmentQueryListVO();

        //按条件搜索
        if(StrUtil.isBlank(condition)){
            IPage<Department> iPage = departmentMapper.selectPage(pages,departmentQueryWrapper);
            List<Department> list = iPage.getRecords();
            Integer count = departmentMapper.selectCount(null);
            departmentQueryListVO.setTotal(count);
            departmentQueryListVO.setDepartmentList(list);
            return departmentQueryListVO;
        }

        departmentQueryWrapper
                .lambda()
                .eq(Department::getDeptNo,condition);

        //精准搜索，直接返回
        if(Optional.ofNullable(departmentMapper.selectCount(departmentQueryWrapper)).orElse(0) >0 ){
            List<Department> departmentList = departmentMapper.selectList(departmentQueryWrapper);
            departmentQueryListVO.setTotal(1);
            departmentQueryListVO.setDepartmentList(departmentList);
            return departmentQueryListVO;
        }

        //清空前置条件
        departmentQueryWrapper.clear();

        departmentQueryWrapper
                .lambda()
                .like(Department::getDeptName,condition)
                .or()
                .like(Department::getManagerName,condition);

        IPage<Department> iPage = departmentMapper.selectPage(pages,departmentQueryWrapper);
        List<Department> list = iPage.getRecords();
        Integer count = departmentMapper.selectCount(departmentQueryWrapper);

        departmentQueryListVO.setTotal(count);
        departmentQueryListVO.setDepartmentList(list);
        return departmentQueryListVO;
    }

    /**
     * 添加部门成员
     * @param departmentUserDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addUser(DepartmentUserDTO departmentUserDTO) {
        Long deptId = departmentUserDTO.getDeptId();

        List<Long> memberIdList = Optional.ofNullable(departmentUserDTO.getMemberSets()).orElse(new LinkedList<>());

        if(memberIdList.isEmpty()){
            throw new MyException(MyExceptionEnum.ONE_MORE_ADD);
        }

        //改变数
        AtomicInteger changeCount = new AtomicInteger();
        //未变数
        AtomicInteger sameCount = new AtomicInteger();

        //新增部门成员:判断该成员是否存在于该部门,不存在则可以添加
        memberIdList.forEach(
                memberId ->{
                    User user = userMapper.selectById(memberId);
                    if(deptId.compareTo(user.getDeptId())!=0){
                        //该部门人数需要修改
                        Department department = getById(user.getDeptId());
                        AtomicInteger atomicInteger = new AtomicInteger(department.getCounts());
                        department.setCounts(Math.max(atomicInteger.decrementAndGet(), 0));
                        updateById(department);

                        user.setDeptId(deptId);
                        user.setDeptName(getById(deptId).getDeptName());
                        userMapper.updateById(user);
                        changeCount.getAndIncrement();
                    }else {
                        sameCount.getAndIncrement();
                    }
                }
        );

        //计算部门人数
        calculateCounts(deptId);

        return "已修改"+changeCount.intValue()+"条数据,未修改数据"+sameCount.intValue()+"条[已存在该部门]";
    }

    /**
     * 移除部门成员
     *   将移除的成员添加到临时部门
     * @param departmentUserDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String removeUser(DepartmentUserDTO departmentUserDTO) {
        Long deptId = departmentUserDTO.getDeptId();

        List<Long> memberIdList = Optional.ofNullable(departmentUserDTO.getMemberSets()).orElse(new LinkedList<>());

        if(memberIdList.isEmpty()){
            throw new MyException(MyExceptionEnum.ONE_MORE_DELETE);
        }

        //移除成功的个数
        AtomicInteger removeCount = new AtomicInteger();

        //未移除的个数
        AtomicInteger retainCount = new AtomicInteger();

        //判断该成员是否属于该部门，是则允许移除
        memberIdList.forEach(
                memberId ->{
                    User user = userMapper.selectById(memberId);
                    if(deptId.compareTo(user.getDeptId()) == 0){
                        //在这个部门中，允许移除
                        user.setDeptId(1L);
                        user.setDeptName("临时部门");

                        userMapper.updateById(user);
                        removeCount.getAndIncrement();
                    }else {
                        //不在这个部门中，不允许移除
                        retainCount.getAndIncrement();
                    }
                }
        );

        calculateCounts(deptId);
        //计算临时部门的人数
        calculateCounts(1L);

        return "已成功移除成员"+removeCount.intValue()+"个,未移除成员"+retainCount.intValue()+"个[不在此部门不允许移除]";
    }

    /**
     * 获取部门的成员列表
     * @param departmentUserQueryDTO
     * @return
     */
    @Override
    public List<UserInfoVO> getDepartmentUserByCondition(DepartmentUserQueryDTO departmentUserQueryDTO) {
        Long departmentId = departmentUserQueryDTO.getDepartmentId();
        String condition = departmentUserQueryDTO.getCondition();

        if(ObjectUtil.isNull(departmentId)){
            throw new MyException(MyExceptionEnum.ID_IS_NULL);
        }

        Integer pageNum = departmentUserQueryDTO.getPageNum();
        Integer pageSize = departmentUserQueryDTO.getPageSize();

        Page<User> page = new Page<>(pageNum,pageSize);

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().eq(User::getDeptId,departmentId);

        if(StrUtil.isNotBlank(condition)){
            userQueryWrapper.lambda().like(User::getRealName,condition);
        }

        List<User> userList = Optional.ofNullable(userMapper.selectPage(page, userQueryWrapper).getRecords()).orElse(new LinkedList<>());

        return userMapStruct.usersToUserInfoVOList(userList);
    }

    //统计部门人数
    private void calculateCounts(Long deptId){
        //重新统计该部门的人数
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().eq(User::getDeptId,deptId);
        Integer persons = Optional.ofNullable(userMapper.selectCount(userQueryWrapper)).orElse(0);
        Department dbDepartment = getById(deptId);
        dbDepartment.setCounts(persons);
        updateById(dbDepartment);
    }

    private void checkDeptNoUsed(DepartmentModelReq departmentModelReq){
        checkUpdateDeptNoUsed(null,departmentModelReq);
    }

    private void checkUpdateDeptNoUsed(String no,DepartmentModelReq departmentModelReq){
        //查看部门号有没有被使用
        String deptNo = departmentModelReq.getDeptNo();
        if(StrUtil.isNotBlank(no) && no.equals(deptNo)){
            return;
        }
        QueryWrapper<Department> departmentQueryWrapper = new QueryWrapper<>();
        departmentQueryWrapper
                .lambda()
                .eq(Department::getDeptNo,deptNo);

        Integer count = departmentMapper.selectCount(departmentQueryWrapper);

        if(count > 0){
            throw new MyException(MyExceptionEnum.USER_NO_USED);
        }
    }
}




